/*
  ==============================================================================

    PluginChainPool.cpp
    Created: 28 Nov 2024 11:43:34am
    Author:  leis

  ==============================================================================
*/

#include "PluginChainPool.h"
PluginChainPool::PluginChainPool()
{
}
PluginChainPool::~PluginChainPool()
{
    std::cout << "PluginChainPool start destroyed" << std::endl;
    for each(auto chain in pluginChains)
    {
        if (chain != nullptr)
        {
            delete chain;
            chain = nullptr;
        }
    }
    pluginChains.clear();
    std::cout << "PluginChainPool is destroyed" << std::endl;
}
void PluginChainPool::Exit()
{
    for each(auto chain in pluginChains)
    {
        if (chain != nullptr)
        {
            delete chain;
            chain = nullptr;
        }
    }
    pluginChains.clear();
}
void PluginChainPool::Init(int initInstanceNum, int maxInstanceNum, int bufferSize, int sampleRate, bool realTime)
{
    this->initInstance = initInstanceNum;
    this->maxInstance = maxInstanceNum;
    this->sampleRate = sampleRate;
    this->bufferSize = bufferSize;
    this->realTime = realTime;
    pluginChains.clear();
    InnerInit();
}
void PluginChainPool::InnerInit()
{
    for (int i = 0; i < this->initInstance; i++)
    {
        int idx = numInstance++;
        AddInstance(idx);
    }
}
PluginChain* PluginChainPool::GetAvaliableChain()
{
    std::lock_guard<std::mutex> lock(mtx);
    if (availableChains.empty() && numInstance < maxInstance)
    {
        int idx = numInstance++;
        AddInstance(idx);
    }
    if (!availableChains.empty())
    {
        int index = availableChains.front();
        availableChains.pop();
        pluginChains[index]->available = false;
        return pluginChains[index];
    }
    return nullptr;
}
PluginChain* PluginChainPool::GetRealTimeChain()
{
    if (realTime)
    {
        return pluginChains[0];
    }
    return nullptr;
}
void PluginChainPool::AddInstance(int index)
{
    PluginChain* chain = new PluginChain(this->sampleRate, this->bufferSize, this->realTime);
    chain->available = true;
    chain->index = index;
    pluginChains.push_back(chain);
    availableChains.push(index);
    std::cout << "AddInstance: " << index << std::endl;
}
void PluginChainPool::MarkChainAsAvailable(int index)
{
    if (index >= 0 && index < pluginChains.size())
    {
        pluginChains[index]->available = true;
        availableChains.push(index);
    }
}
bool PluginChainPool::CheckChainAvailable()
{
    if (!availableChains.empty() || numInstance < maxInstance)
        return true;
    return false;
}